﻿using System;
using System.Threading;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
using NHibernate;
using NHibernate.Context;

using ZQNB.BaseLib.Accounts.Events;
using ZQNB.BaseLib.Core;
using ZQNB.Common.Events;
using ZQNB.Common.Ioc;
using ZQNB.Common.Logs;
using ZQNB.Common.NHExtensions;
using ZQNB.Common.Web;
using ZQNB.Web.Common.Contexts;

namespace ZQNB.Web
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            //SetupConfigHelper setupConfigHelper = new SetupConfigHelper();
            //var recreateDb = setupConfigHelper.GetRecreateDb();
            //string dbName = setupConfigHelper.GetDbName();
            
            //setup nhibernate
            const bool recreateDb = true;
            const string dbName = "NbV4Db";
            //开发时用（数据库由程序自动生成）
            NHibernateConfig.SetupNHibernate(dbName, recreateDb);
            ApplicationStartBindSession();

            //ioc setup
            NinjectConfig.SetupCore();
            NinjectConfig.SetupAdapterResolvers();
            NinjectConfig.LoadModules();
            
            //site health status
            var siteContext = CoreServiceProvider.LocateService<NbSiteContext>();
            ISiteHealthStatusService siteHealthStatusService = siteContext;
            siteHealthStatusService.ApplicationStart();

            MetaConfig.RegisterMetas();

            WidgetMetaConfig.Register();

            //FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            //webapi，Mvc的路由注册
            GlobalConfiguration.Configure(WebApiConfig.Register);
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            //Area级别的注册
            NbAreaRegistration.RegisterAllAreasInvoke();

            //处理重要的事件
            RegisterEvents();
            
            ////一些重要的设置项
            //AntiForgeryConfig.UniqueClaimTypeIdentifier = NbClaimTypes.UserName;
            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Add(new NbViewEngine());
        }

        private void RegisterEvents()
        {
            DomainEvents.Register<UserLoginEvent>(HelloWatcher2.WhenUserLogin);
            DomainEvents.Register<UserLogoutEvent>(HelloWatcher2.WhenUserLogout);
        }

        protected void Application_End()
        {
            //site health status
            var siteContext = CoreServiceProvider.LocateService<NbSiteContext>();
            ISiteHealthStatusService siteHealthStatusService = siteContext;
            siteHealthStatusService.ApplicationEnd();
        }

        protected void Application_BeginRequest()
        {
            //start new NHibernate session on each web request
            ISession session = NbSessionFactoryForWeb.OpenSession();
            CurrentSessionContext.Bind(session);
        }
        
        protected void Application_EndRequest()
        {
            ISession session = CurrentSessionContext.Unbind(NbSessionFactoryForWeb.SessionFactory());
            if (session != null)
            {
                session.Dispose();
            }

            if (Context.Response.StatusCode == 302 &&
                 Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
            {
                Context.Response.Clear();
                Context.Response.StatusCode = 401;
            }
        }

        private void ApplicationStartBindSession()
        {
            //修正 Illegally attempted to associate a proxy with two open Sessions 的bug
            //原因是Application_Start()开始于Application_BeginRequest()之前
            string theMessage = string.Format("{0} =============>", "ApplicationStartBindSession()");
            ILogger logger = this.GetLogger();
            logger.Info(theMessage);

            //start new NHibernate session
            ISession session = NbSessionFactoryForWeb.OpenSession();
            CurrentSessionContext.Bind(session);
        }
    }

    public class HelloWatcher2
    {
        public static void WhenUserLogin(UserLoginEvent args)
        {
            string message = string.Format("[HelloWatcher2] -> {0} logged in! -> {1}", args.LoginName, Thread.CurrentThread.ManagedThreadId);
            System.Diagnostics.Debug.WriteLine(message);
        }

        public static void WhenUserLogout(UserLogoutEvent args)
        {
            string message = string.Format("[HelloWatcher2] -> {0} logged out! -> {1}", args.LoginName, Thread.CurrentThread.ManagedThreadId);
            System.Diagnostics.Debug.WriteLine(message);
        }
    }

    public class HelloWatcher : IHandle<UserLoginEvent>, IHandle<UserLogoutEvent>
    {
        public void Handle(UserLoginEvent args)
        {
            string message = string.Format("[HelloWatcher] -> {0} logged int! -> {1}", args.LoginName, Thread.CurrentThread.ManagedThreadId);
            System.Diagnostics.Debug.WriteLine(message);
            //System.Diagnostics.Debug.WriteLine(args.LoginName + " has logged in! I get it!" + DateTime.Now);
            //for (int i = 0; i < 1000; i++)
            //{
            //    Thread.Sleep(10);
            //    System.Diagnostics.Debug.WriteLine(args.LoginName + " has logged in! I get it!");
            //}
        }

        public void Handle(UserLogoutEvent args)
        {
            string message = string.Format("[HelloWatcher] -> {0} logged out! -> {1}", args.LoginName, Thread.CurrentThread.ManagedThreadId);
            System.Diagnostics.Debug.WriteLine(message);
            //System.Diagnostics.Debug.WriteLine(args.LoginName + " has logged out! I get it!" + DateTime.Now);
            //for (int i = 0; i < 1000; i++)
            //{
            //    Thread.Sleep(10);
            //    System.Diagnostics.Debug.WriteLine(args.LoginName + " has logged out! I get it!" + DateTime.Now);
            //}
        }
    }
}
